package com.qyer.search.servlet;

import static com.qyer.commons.utils.CommonUtils.cast2Boolelan;
import static com.qyer.commons.utils.CommonUtils.cast2Int;
import static com.qyer.commons.utils.CommonUtils.cast2String;
import static com.qyer.log.WarningLogger.logWarning;

import static com.qyer.search.enums.SearchError.INVALID_PARAMETER;
import static com.qyer.search.enums.SearchError.PLAN_FAILED;
import static com.qyer.search.enums.SearchError.RESULT_PROCESSING_ERROR;
import static com.qyer.search.enums.SearchError.SEARCH_FAILED;
import static com.qyer.search.model.result.SearchMetaInfo.EMPTY_SEARCH_META_INFO;
import static com.qyer.search.utils.ModelUtils.packageAll;
import static com.qyer.search.utils.ModelUtils.packageBySTG;
import static com.qyer.search.utils.ModelUtils.packageByType1;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qyer.commons.blender.Blender;
import com.qyer.commons.blender.BlenderLayoutPattern;
import com.qyer.commons.blender.keyconverter.StringIntConverter;
import com.qyer.log.ErrorLogger;
import com.qyer.log.PhraseShowLogger;
import com.qyer.log.TimeCostLogger;
import com.qyer.log.WarningLogger;
import com.qyer.search.Constants;
import com.qyer.search.DeserializerProcessor.DeserializerProcessor;
import com.qyer.search.DeserializerProcessor.DeserializerProcessorWithNoType;
import com.qyer.search.DeserializerProcessor.VSKUDeserializerAllProcessor;
import com.qyer.search.DeserializerProcessor.*;

import com.qyer.search.annotation.TemplateName;
import com.qyer.search.cache.mutable.MutableCaches;
import com.qyer.search.engine.ForkJoinESEngine;
import com.qyer.search.enums.FieldsMode;
import com.qyer.search.exception.BlendException;
import com.qyer.search.exception.InvalidParameterException;
import com.qyer.search.exception.SearchException;
import com.qyer.search.filter.AbstractFilter;
import com.qyer.search.filter.AbstractIDFilter;
import com.qyer.search.filter.ChannelFilter;
import com.qyer.search.filter.ChannelWithIDFilter;
import com.qyer.search.filter.OnSaleTimeFilter;
import com.qyer.search.filter.OnSaleTimeIDFilter;
import com.qyer.search.filter.StartTimeFilter;
import com.qyer.search.filter.StartTimeIDFilter;
import com.qyer.search.model.SearchParameterEntity;
import com.qyer.search.model.aggregation.STGInfo;
import com.qyer.search.model.aggregation.Segment;
import com.qyer.search.model.ZTagEntity;
import com.qyer.search.model.aggregation.AggregationProduct;
import com.qyer.search.model.aggregation.AggregationRegular;
import com.qyer.search.model.aggregation.Intention;
import com.qyer.search.model.aggregation.Prefer;
import com.qyer.search.model.lastminute.LightZSKU;
import com.qyer.search.model.lastminute.SKU;
import com.qyer.search.model.lastminute.VSKU;
import com.qyer.search.model.mutable.IndexMap;
import com.qyer.search.model.mutable.Place;
import com.qyer.search.model.mutable.ProductSnapshot;
import com.qyer.search.model.result.SearchEntity;
import com.qyer.search.model.result.SearchFilterInfo;
import com.qyer.search.model.result.SearchMetaInfo;
import com.qyer.search.model.result.SearchPackage;
import com.qyer.search.model.result.Type1SearchEntity;
import com.qyer.search.model.result.Type1SearchPackage;
import com.qyer.search.model.result.VInnerResult;
import com.qyer.search.model.result.VResult;
import com.qyer.search.report.ReporterQueue;
import com.qyer.search.report.SearchReportItem;
import com.qyer.search.report.TimeCost;
import com.qyer.search.report.VSearchReportItem;
import com.qyer.search.searchplan.SQPlan2;
import com.qyer.search.searchplan.SQPlan3;
import com.qyer.search.searchplan.SQPlanner;
import com.qyer.search.sort.PriceSorter;
import com.qyer.search.sort.SalesSorter;
import com.qyer.search.sort.Type1Sorter;
import com.qyer.search.sort.VPriceSorter;
import com.qyer.search.sort.VPriceTimSorter;
import com.qyer.search.sort.VPriceTimSorterNoMarket;
import com.qyer.search.sort.VPriceTimSorterNoMarket2;
import com.qyer.search.sort.VSalesSorter;
import com.qyer.search.sort.VSalesTimSorter;
import com.qyer.search.sort.VSalesTimSorterNoMarket;
import com.qyer.search.sort.VSalesTimSorterNoMarket2;
import com.qyer.search.sort.VType1Sorter;
import com.qyer.search.sort.VType1Sorter2;
import com.qyer.search.template.VMTemplate;
import com.qyer.search.threading.DeserializerThreadPoolHolder;
import com.qyer.search.utils.BlenderUtils;
import com.qyer.search.utils.DestinationUtils;
import com.qyer.search.utils.ListUtils;
import com.qyer.search.utils.ModelUtils;
import com.qyer.search.utils.SplitStringUtils;
import com.qyer.search.utils.WordETLClient;
import com.qyer.words.model.Impression;
import com.qyer.words.model.Word;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * Created by tangzheng on 16/6/12.
 */
@TemplateName("search_latest.vm")
public class CacheSearchServlet extends AbstractServlet {

  private static final Logger LOGGER = LoggerFactory.getLogger(BasicSearchServlet.class);

  private static final String DEFAULT_STRA = "gorder";

  private void report(SearchReportItem sri, TimeCost timeCost) throws JsonProcessingException {
    TimeCostLogger.logTimeCost(sri.getSearchParameter(), timeCost);
    try {
      ReporterQueue.getInstance().putToQueue(sri);
    } catch (InterruptedException e) {
      LOGGER.error("Interrupt reporting.", e);
    }
  }

  @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws
    ServletException, IOException {
    long beginTime = System.currentTimeMillis();
    resp.setContentType("text/html");
    resp.setCharacterEncoding("utf-8");
    String strategy = DEFAULT_STRA;
    SearchParameterEntity searchParameterOrigin = null;
    try {
      searchParameterOrigin = new SearchParameterEntity(req, resp, this);
    }catch (Exception e){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, e);
      return;
    }
    try {
      checkParam(searchParameterOrigin);
    } catch (Exception e) {
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, e);
      return;
    }

    // 使用简单结果(只有id)
    boolean useSimpleResult = cast2Boolelan(req.getParameter("simple"));
    // 展示模式(可视化界面 or Json数据)
    boolean onlyData = cast2Boolelan(req.getParameter("only_data"), true);
    // 混排模式(按照一级类目分开 or 混排)
    boolean blendAll = cast2Boolelan(req.getParameter("blend_all"), false);
    String blendString = cast2String(req.getParameter("blend_str"));
    int result_mode, p_start, p_end;
    int limit = Constants.DEFAULT_LIMIT;
    try {
      result_mode = cast2Int(req.getParameter("r_mode"), 0);
      p_start = cast2Int(req.getParameter("p_from"), 0);
      p_end = cast2Int(req.getParameter("p_to"), Constants.DEFAULT_LIMIT_1);
    }catch (Exception e){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, e);
      return;
    }
    if(p_start > p_end){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, new InvalidParameterException("偏移错误"));
      return;
    }
    //boolean basic_data = cast2Boolelan(req.getParameter("basic"), false);

    boolean meta_data = cast2Boolelan(req.getParameter("meta_info"), false);
    boolean isOnlyType = true;
    //
    List<AbstractIDFilter> filters = new ArrayList<>();
    //
    String channels = cast2String(req.getParameter("channel"));
    int channel = 0;
    if(Constants.ChannelMap.containsKey(channels)) {
      if (StringUtils.isNotBlank(channels)) {
        filters.add(new ChannelWithIDFilter(SplitStringUtils.splitTostrs(channels, Constants.SEPARATOR_PARAMETER)));
      }
      channel = Constants.ChannelMap.get(channels);
    }else {
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, new InvalidParameterException("channel is only for one source."));
      return;
    }
    try {
      searchParameterOrigin.isVStypeOK(channel);
    }catch (Exception e){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, e);
      return;
    }
    //出发时间筛选 yyyyMM
    long start = 0;
    long end = 0;
    String startStr = cast2String(req.getParameter("from"));
    String endStr = cast2String(req.getParameter("to"));

    try {
      if (!(StringUtils.isBlank(startStr) && StringUtils.isBlank(endStr))) {
        if (StringUtils.isBlank(startStr)) {
          start = new DateTime().millisOfDay().withMinimumValue().getMillis() / 1000;
          startStr = "今天";
        }
        else
          start = DateTimeFormat.forPattern("yyyyMMdd").parseDateTime(startStr).getMillis() / 1000;
        if (StringUtils.isBlank(endStr)) {
          end = Long.MAX_VALUE;
          endStr = "之后";
        }
        else {
          end = DateTimeFormat.forPattern("yyyyMMdd").parseDateTime(endStr).getMillis() / 1000;
          endStr = "---" + endStr;
        }

        if(start >= end)
          throw new InvalidParameterException("参数异常");
        else {
          filters.add(new StartTimeIDFilter(start, end));
          isOnlyType = false;
        }
      }

    }catch (Exception e){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, e);
      return;
    }

    long onsaleTimeStart = 0;
    long onsaleTimeEnd = Long.MAX_VALUE;
    String onsaleTodyFrom = cast2String(req.getParameter("on_from"));
    String onsaleTodyTo = cast2String(req.getParameter("on_to"));
    //System.out.println("onsaleTodyFrom:"+onsaleTodyFrom);
    //System.out.println("onsaleTodyTo:"+onsaleTodyTo);
    if (StringUtils.isNotBlank(onsaleTodyFrom)||StringUtils.isNotBlank(onsaleTodyTo)){
      if(StringUtils.isNotBlank(onsaleTodyFrom))
        onsaleTimeStart = DateTimeFormat.forPattern("yyyyMMdd").parseDateTime(onsaleTodyFrom).getMillis() / 1000;
      if(StringUtils.isNotBlank(onsaleTodyTo))
        onsaleTimeEnd = DateTimeFormat.forPattern("yyyyMMdd").parseDateTime(onsaleTodyTo).getMillis()/1000;
      filters.add(new OnSaleTimeIDFilter(onsaleTimeStart, onsaleTimeEnd));
      isOnlyType = false;
    }

    String startStr1 = cast2String(req.getParameter("t_from"));
    String endStr1 = cast2String(req.getParameter("t_to"));
    if(!StringUtils.isEmpty(startStr1)){
      byte [] sts = startStr1.getBytes();
      System.out.println("---------------------------A UNIXTIME START---------------------------");
      for(int i = 0; i < sts.length; i++){
        System.out.println(sts[i]);
      }
      System.out.println("---------------------------A UNIXTIME   END---------------------------");
    }
    if(!StringUtils.isEmpty(endStr1)){
      byte [] ets = endStr1.getBytes();
      System.out.println("---------------------------B UNIXTIME START---------------------------");
      for(int i = 0; i < ets.length; i++){
        System.out.println(ets[i]);
      }
      System.out.println("---------------------------B UNIXTIME   END---------------------------");
    }


    String startTimeShow = "";

    if((startStr == null)&&(endStr == null))
      startTimeShow = "全部";
    else
      startTimeShow = startStr + endStr;

    String limitStr = "全部";
    try {
      limitStr = req.getParameter("limit");
      if(limitStr != null) {
        limit = cast2Int(limitStr, Integer.MAX_VALUE);
        if(limit < 0) {
          writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, new InvalidParameterException("limit 为负"));
          return;
        }
      }
      else
        limitStr = "全部";
    }catch (Exception e){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, e);
      return;
    }

    //System.out.println("~~:"+searchParameterOrigin.getUserInputKW());
    //排序选择
    String sortRegular;
    int sort = 0;
    try {
      sortRegular = req.getParameter("sort");
      sort = cast2Int(sortRegular, 0);
    }catch (Exception e){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, e);
      return;
    }

    // 词汇处理
    long t1 = System.currentTimeMillis();
    String userInputKW = searchParameterOrigin.getUserInputKW();
    Set<List<Word>> tuples = null;
    try {
      tuples = WordETLClient.getInstance().
        getBasicWord(userInputKW, searchParameterOrigin.getRequestId());
    } catch (Exception e) {
      //WarningLogger.logWarning("Cannot etl user input keywords.", searchParameterOrigin, e);
      Word word = new Word(userInputKW);
      try {
        PhraseShowLogger
          .logSplitResult("hmm", searchParameterOrigin.getRequestId(), "hanmeimeiError", word);
      } catch (Exception ee) {
        LOGGER.warn("Cannot send report({})", e);
      }
      List<Word> list = new ArrayList<>();
      list.add(word);
      tuples = new HashSet<>();
      tuples.add(list);
    }

    //System.out.println("分词结果:" + tuples);
    List<Integer> stgOr = new ArrayList<>();
    Prefer prefer = null;
    //System.out.println("分词时间:"+(System.currentTimeMillis() - t1));
    //searchParameterOrigin.addTypes(tuples);
    Set<Integer> preSKUType1 = new HashSet<>();
    Set<Integer> preSKUType2 = new HashSet<>();
    boolean local = false;

    //意图判断
    //getIntention(searchParameterOrigin, tuples, preSKUType1, preSKUType2);
    List<Segment> segmentation = getIntention2(searchParameterOrigin, tuples, preSKUType1, preSKUType2, channel);
    if(!searchParameterOrigin.isValidDestination()){
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, new InvalidParameterException("目的地国家城市不匹配"));
      return;
    }
    //
    long t2 = System.currentTimeMillis();
    //System.out.println("词分析时间:"+(t2-t1));
    //System.out.println("词分析时:"+tuples);
    // 构建搜索/查询Plan
    List<SQPlan3> plans;

    try {
      plans = SQPlanner.doPlan5(searchParameterOrigin, tuples, channel);
    } catch (Exception e) {
      e.printStackTrace();
      writeError(searchParameterOrigin, resp, beginTime, PLAN_FAILED, e);
      return;
    }
    // 执行搜索
    long t3 = System.currentTimeMillis();
    ///////////////////////////////////////////////////////////////////
    boolean isType1Cache = false;
    SearchFilterInfo searchFilterInfo = null;
    List<? extends SearchEntity> finalPackage = null;
    VResult vResult = null;
    AggregationProduct searchCensus = null;
    Set<Integer> setStg = null;
    List<Type1SearchEntity> sortedEntities;
    if(meta_data)
      searchCensus = new AggregationProduct();
    else
      setStg = new HashSet<>();
    ////////////////////////////////////////大类mutable缓存/////////////////////////////////////////////////////
    if(searchParameterOrigin.isOnlyCategory()){
      /*System.out.println("isOnlyCategory");
      if(isOnlyType)
        System.out.println("isOnlyType");
      if(sort == 0)
        System.out.println("sort==0");
      if(!blendAll)
        System.out.println("blend");
      if(onlyData)
        System.out.println("only");
      if(result_mode == 0)
        System.out.println("rm");*/
      if(isOnlyType && (sort == 0) && (!blendAll) && onlyData && (result_mode == 0)){
        ////////////////////////////
        //System.out.println("filters empty");
        int type1Cache = -1;
        for(int tt : searchParameterOrigin.getType1s())
          type1Cache = tt;
        Map<Integer, Map<Integer, AggregationProduct>> tmp = MutableCaches.getInstance().P_SNAPSHOT.getCacheContent().getStg_census();
        if(tmp != null) {
          searchCensus = MutableCaches.getInstance().P_SNAPSHOT.getCacheContent().getStg_census()
                                                               .get(channel).get(type1Cache);
          sortedEntities = MutableCaches.getInstance().P_SNAPSHOT.getCacheContent().getStg_entity()
                                                                 .get(channel).get(type1Cache);

          if (sortedEntities != null) {
            isType1Cache = true;
            try {
              //System.out.println("非混排");
              List<SearchEntity> finalPackage1 = new ArrayList<>();
              Map<Integer, VInnerResult> map = new HashMap<>();
              for (int i = 0; i < sortedEntities.size(); i++) {
                Type1SearchEntity type1SearchEntity = sortedEntities.get(i).copy();
                type1SearchEntity.sub(p_start, p_end);
                int _type = type1SearchEntity.getType1();

                map.put(_type, type1SearchEntity.getMap(p_start, p_end));
                finalPackage1.add(type1SearchEntity);
              }
              finalPackage = finalPackage1;
              vResult = new VResult(map);
            } catch (Exception e) {
              e.printStackTrace();
              System.out.println(e.toString());
            }
            Map<Integer, Integer> order_map = MutableCaches.getInstance().Z_TAG_SNAPSHOT
              .getCacheContent().getvStypeMap().get(channel).getOrder_STG();
            if (meta_data)
              prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, searchCensus);
            else
              prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, setStg);

            if (CollectionUtils.isEmpty(finalPackage))
              finalPackage = new ArrayList<>();
            SearchReportItem sri = new SearchReportItem(searchParameterOrigin, transfer(finalPackage));
            TimeCost tc = new TimeCost(t2 - t1, t3 - t2, 0, 0, 0, (System.currentTimeMillis() - beginTime))
              .addTime("blend-result", 0);
            //修正
            report(sri, tc);

            Intention intention = new Intention(prefer, segmentation);
            if (meta_data) {
              //searchCensus.sort();
              searchFilterInfo = new SearchFilterInfo(searchCensus.getStg_info(), stgOr, intention);
            } else {
              searchFilterInfo = null;
            }
            //System.out.println("Cache hit STG:" + type1Cache);
            writeOK(resp, beginTime, searchParameterOrigin.getRequestId(), strategy, vResult,
                    searchFilterInfo);
            return;
            ////////////////////////////
          }
          /////////////////////
        }
      }else if(isOnlyType && (sort == 2) && onlyData && (result_mode == 0)){
        //System.out.println("SORT@2");
        int type1Cache = -1;
        for(int tt : searchParameterOrigin.getType1s())
          type1Cache = tt;
        //System.out.println("TYPE:"+type1Cache);
        try {
          Map<Integer, Map<Integer, Map<Integer, List<SearchEntity>>>> ps = MutableCaches
            .getInstance().P_SNAPSHOT.getCacheContent().getStg_sort_entity();
          if (ps != null) {
            //System.out.println("in");
            searchCensus = MutableCaches.getInstance().P_SNAPSHOT.getCacheContent().getStg_census()
                                                                 .get(channel).get(type1Cache);
            List<SearchEntity> searchEntityList = MutableCaches.getInstance().P_SNAPSHOT
              .getCacheContent().getStg_sort_entity().get(channel).get(type1Cache).get(sort);
            SearchEntity searchEntity = searchEntityList.get(0);
            List<VSKU> vskuList = Lists.newArrayListWithCapacity(p_end - p_start);
            List<VSKU> skus = searchEntity.getSkus();
            for (int i = p_start; (i < p_end && i < searchEntity.getPackageSize()); i++) {
              vskuList.add(skus.get(i));
            }
            Type1SearchEntity type1SearchEntity = new Type1SearchEntity(type1Cache);
            type1SearchEntity.addSkus(vskuList);
            type1SearchEntity.setPackageSize(searchEntity.getPackageSize());
            vResult = getResullt(type1SearchEntity, type1Cache);
            List<SearchEntity> lt = new ArrayList<>();
            lt.add(type1SearchEntity);
            finalPackage = lt;
            //System.out.println("go");
            SearchReportItem sri = new SearchReportItem(searchParameterOrigin, transfer(finalPackage));
            TimeCost tc = new TimeCost(t2 - t1, t3 - t2, 0, 0, 0, (System.currentTimeMillis() - beginTime))
              .addTime("blend-result", 0);
            //修正
            report(sri, tc);
            Map<Integer, Integer> order_map = MutableCaches.getInstance().Z_TAG_SNAPSHOT
              .getCacheContent().getvStypeMap().get(channel).getOrder_STG();
            if (meta_data)
              prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, searchCensus);
            else
              prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, setStg);

            Intention intention = new Intention(prefer, segmentation);
            if (meta_data) {
              //searchCensus.sort();
              searchFilterInfo = new SearchFilterInfo(searchCensus.getStg_info(), stgOr, intention);
            } else {
              searchFilterInfo = null;
            }
            //System.out.println("Cache hit STG:" + type1Cache);
            writeOK(resp, beginTime, searchParameterOrigin.getRequestId(), "sdown", vResult,
                    searchFilterInfo);
            return;

          }
        }catch (Exception e){
          e.printStackTrace();
        }
      }
    }
    /////////////////////////////////////////////////////////////////////////////////////////////
    //System.out.println("搜索计划时间:"+(t3-t2));

    // JsonString的反序列化工作交给App层面
    Set<String> searchResultStringList = new HashSet<>();
    int plansize = 0;
    if(CollectionUtils.isNotEmpty(plans))
      plansize = plans.size();
    try {
      if ((result_mode == 0)) {
        //System.out.println("ForkJoinESEngine go");
        /*if (meta_data)
          searchResultStringList = ForkJoinESEngine.getInstance()
                                                   .forkSearch(searchParameterOrigin, plans,
                                                               false, FieldsMode.LIGHT);
        else
          searchResultStringList = ForkJoinESEngine.getInstance()
                                                   .forkSearch(searchParameterOrigin, plans,
                                                               false, FieldsMode.LESSLIGHT);*/

        /////////////////////////////////////////
        /*if(meta_data)
          searchResultStringList = ForkJoinESEngine.getInstance()
                                                   .forkSearchSimple(searchParameterOrigin, plans,
                                                                     false, FieldsMode.LIGHT);
        else
          searchResultStringList = ForkJoinESEngine.getInstance()
                                                   .forkSearchSimple(searchParameterOrigin, plans,
                                                                     false, FieldsMode.LESSLIGHT);*/
        /////////////////////////////////////////////
        searchResultStringList = ForkJoinESEngine.getInstance()
                                                 .forkSearchSimple(searchParameterOrigin, plans,
                                                                   false, FieldsMode.SIMPLE);
        /////////////////////////////////////////////////////////////////
      }

      //===============测试=====================
      //===============测试=====================
    } catch (SearchException e) {
      writeError(searchParameterOrigin, resp, beginTime, SEARCH_FAILED, e);
      return;
    }
    // 整理结果(必须按照type1整理, 因为目前排序是只能按照type1排序)
    long t4 = System.currentTimeMillis();
    long t5 = 0;
    long t6 = 0;
    long t7 = 0;
    long transformMergeResultTime = 0;
    int type1Size = MutableCaches.getInstance().Z_TAG_SNAPSHOT
                                               .getCacheContent()
                                               .getvStypeMap()
                                               .get(channel)
                                               .getS_type_group_set()
                                               .size();

    //SearchMetaInfo metaInfo = EMPTY_SEARCH_META_INFO;
    SearchMetaInfo metaInfo;
    List<Type1SearchPackage> packages = null;
    SearchPackage searchPackage = null;
    //List<? extends SearchEntity> finalPackage = null;
    //VResult vResult = null;

    List<Type1SearchEntity> entities = null;
    SearchEntity searchEntity = null;
    List<? extends SearchEntity> finalEntity = null;

    //聚合原则
    AggregationRegular regular = searchParameterOrigin.getAggregationRegular(channel);
    /////////-------------------------------------------------------------////////
    String cityStr = regular.getCity();
    String countryStr = regular.getCountry();
    String continentName = regular.getContinent();
    List<Place> places = DestinationUtils.getDestination(cityStr, countryStr, continentName);
    regular.setPlaces(places);
    ////////---------------------------------------------------------------////
    //System.out.println(regular.toString());
    //聚合体生成
    /*AggregationProduct searchCensus = null;
    Set<Integer> setStg = null;
    if(meta_data)
      searchCensus = new AggregationProduct();
    else
      setStg = new HashSet<>();*/
    int searchResultSize = searchResultStringList.size();
    int count = 0;
    int rest = 0;

    count = searchResultSize/Constants.SEARCH_THRESHOLD;
    rest = searchResultSize%Constants.SEARCH_THRESHOLD;
    if(rest > Constants.HALF_SEARCH_THRESHOLD){
      count++;
    }
    List<String> sr_StringList = new ArrayList<>(searchResultStringList);
    //sr_StringList.addAll(searchResultStringList);
    int count1 = count - 1;
    if((sort == 0) && (!isType1Cache)) {
      if (count > 1) {
        //System.out.println("使用线程池.");
        if(meta_data) {
          ExecutorService service = DeserializerThreadPoolHolder.getInstance().getService();
          List<Future<List<Type1SearchEntity>>> futures = Lists.newArrayListWithCapacity(count);
          List<String> stringList = null;
          List<AggregationProduct> aggList = Lists.newArrayListWithCapacity(count);
          //
          for (int i = 0; i < count; i++) {

            //long s11 = System.currentTimeMillis();
            //System.out.println("count:");
            if (i != count1) {
              stringList = sr_StringList
                .subList(i * Constants.SEARCH_THRESHOLD, (i + 1) * Constants.SEARCH_THRESHOLD);
            } else {
              stringList = sr_StringList.subList(i * Constants.SEARCH_THRESHOLD, searchResultSize);

            }

            AggregationProduct agg = new AggregationProduct();
            CacheProcessor processor = new CacheProcessor(
              searchParameterOrigin, stringList, result_mode, filters, agg, regular, System.currentTimeMillis());
            aggList.add(agg);
            futures.add(service.submit(processor));
          }
          //System.out.println("thread start time:"+(System.currentTimeMillis() - t4));
          //获得结果
          boolean isHit = false;
          entities = Lists.newArrayListWithCapacity(type1Size);
          List<Type1SearchEntity> t1list;
          for (int i = 0; i < count; i++) {
            try {
              t1list = futures.get(i).get(2000, TimeUnit.MILLISECONDS);
              int size_future = t1list.size();
              for (int j = 0; j < size_future; j++) {
                Type1SearchEntity ttemp = t1list.get(j);
                ////////////////////////////////////////////
                ////////////////////////////////////////////
                int c1 = ttemp.getType1();
                for (int k = 0; k < entities.size(); k++) {
                  Type1SearchEntity ttemp2 = entities.get(k);
                  int c11 = ttemp2.getType1();
                  if (c11 == c1) {
                    ttemp2.add(ttemp);
                    isHit = true;
                    break;
                  } else {
                    continue;
                  }
                }
                if (!isHit) {
                  entities.add(ttemp);
                }
                isHit = false;
              }
              if (meta_data) {
                searchCensus.add(aggList.get(i));
              }
              //////////////////////////////////////////////////////////
            } catch (Exception e) {
              e.printStackTrace();
              ErrorLogger.logError(searchParameterOrigin, e);
            }
          }
          //System.out.println("time:"+(System.currentTimeMillis() - t4));
          //
        }else {
          ExecutorService service = DeserializerThreadPoolHolder.getInstance().getService();
          List<Future<List<Type1SearchEntity>>> futures = Lists.newArrayListWithCapacity(count);
          List<String> stringList = null;
          List<Set<Integer>> aggList = Lists.newArrayListWithCapacity(count);
          //
          for (int i = 0; i < count; i++) {

            //long s11 = System.currentTimeMillis();
            //System.out.println("count:");
            if (i != count1) {
              stringList = sr_StringList
                .subList(i * Constants.SEARCH_THRESHOLD, (i + 1) * Constants.SEARCH_THRESHOLD);
            } else {
              stringList = sr_StringList.subList(i * Constants.SEARCH_THRESHOLD, searchResultSize);

            }

            Set<Integer> agg = new HashSet<>();
            CacheNoMetaProcessor processor = new CacheNoMetaProcessor(
              searchParameterOrigin, stringList, result_mode, filters, agg, regular, System.currentTimeMillis());
            aggList.add(agg);
            futures.add(service.submit(processor));
          }
          //System.out.println("thread start time:"+(System.currentTimeMillis() - t4));
          //获得结果
          boolean isHit = false;
          entities = Lists.newArrayListWithCapacity(type1Size);
          List<Type1SearchEntity> t1list;
          for (int i = 0; i < count; i++) {
            try {
              t1list = futures.get(i).get(1000, TimeUnit.MILLISECONDS);
              int size_future = t1list.size();
              for (int j = 0; j < size_future; j++) {
                Type1SearchEntity ttemp = t1list.get(j);
                int c1 = ttemp.getType1();
                for (int k = 0; k < entities.size(); k++) {
                  Type1SearchEntity ttemp2 = entities.get(k);
                  int c11 = ttemp2.getType1();
                  if (c11 == c1) {
                    ttemp2.add(ttemp);
                    isHit = true;
                    break;
                  } else {
                    continue;
                  }
                }
                if (!isHit) {
                  entities.add(ttemp);
                }
                isHit = false;
              }
              if (!meta_data) {
                if(CollectionUtils.isNotEmpty(aggList.get(i))){
                  setStg.addAll(aggList.get(i));
                }
              }
              //////////////////////////////////////////////////////////
            } catch (Exception e) {
              ErrorLogger.logError(searchParameterOrigin, e);
            }
          }
        }

      }else {
        //System.out.println("未用线程池.");
        //WarningLogger.logWarning("sort:0", searchParameterOrigin, null);
        long t12 = System.currentTimeMillis();

        if(meta_data) {
          entities = packageBySTG(searchParameterOrigin, sr_StringList, filters, regular,
                                  searchCensus, result_mode);
          /*if (CollectionUtils.isNotEmpty(filters)) {
            entities = packageBySTG(searchParameterOrigin, sr_StringList, filters, regular,
                                    searchCensus, result_mode);
          } else {
            entities = packageBySTG(searchParameterOrigin, sr_StringList, null, regular,
                                    searchCensus, result_mode);
          }*/
        }else {
          entities = packageBySTG(searchParameterOrigin, sr_StringList, filters, regular,
                                  setStg, result_mode);
          /*if (CollectionUtils.isNotEmpty(filters)) {
            entities = packageBySTG(searchParameterOrigin, sr_StringList, filters, regular, setStg,
                                    result_mode);
          } else {
            entities = packageByType1(searchParameterOrigin, sr_StringList, null, regular,
                                      setStg, result_mode);
          }*/
        }
        //System.out.println("检测序列化时间:" + (System.currentTimeMillis() - t12));
      }
      //排序
      t5 = System.currentTimeMillis();
      transformMergeResultTime = t5 - t4;
      //System.out.println("GMV反序列化时间:"+transformMergeResultTime);

      // 排序
      long t11 = System.currentTimeMillis();
      //List<Type1SearchPackage> sortedPackages;
      //List<Type1SearchEntity> sortedEntities;
      //-----------------------------------------------------------------------------------------------------------------------------
      Map<Integer, Integer> order_map = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                  .getvStypeMap()
                                                                                  .get(channel)
                                                                                  .getOrder_STG();
      if(meta_data)
        prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, searchCensus);
      else
        prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, setStg);
      //-----------------------------------------------------------------------------------------------------------------------------
      ///////////////////////
      /*for(Type1SearchEntity entity:entities){
        System.out.println("Entity STGID:" + entity.getType1() + "------SIZE:" + entity.getPackageSize());
      }*/
      ///////////////////////
      try {
        if(blendAll){
          sortedEntities = new VType1Sorter2(searchParameterOrigin, entities, channel)
            .sortWithoutMarket(preSKUType1, preSKUType2);
        }else {
          sortedEntities = new VType1Sorter2(searchParameterOrigin, entities, channel)
            .sort(preSKUType1, preSKUType2);
        }
      } catch (SearchException e) {
        logWarning("Sorting failed", searchParameterOrigin, e);
        //sortedPackages = packages;
        sortedEntities = entities;
      }
      ////////////////////////////////
      /*for(Type1SearchEntity entity:entities){
        System.out.println("SORT Entity STGID:" + entity.getType1() + "------SIZE:" + entity.getPackageSize());
      }*/
      ///////////////////////////////

      //System.out.println("排序");
      t6 = System.currentTimeMillis();
      //System.out.println("排序时间:"+(t6 - t11));
      Map<Integer, Integer> stgOrderMap = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                    .getvStypeMap()
                                                                                    .get(channel)
                                                                                    .getOrder_STG();
      List<VSKU> vskuLists = new ArrayList<>();
      List<VSKU> marketLists = new ArrayList<>();
      List<Type1SearchEntity> sortedEntities1 = new ArrayList<>();
      int blend_size = 0;
      int final_size = 0;
      if (blendAll&& CollectionUtils.isNotEmpty(sortedEntities)) {
        //////////////////////////////////////////////////////////////
        List<VSKU> vSKUResultList = new ArrayList<>();
        try {
          List<VSKU> preferSkus;
          List<VSKU> generalSkus;

          Map<Integer, List<VSKU>> preferSkusMap = new HashMap<>(type1Size);
          Map<Integer, List<VSKU>> generalSkusMap = new HashMap<>(type1Size);
          for (Type1SearchEntity type1SearchEntity : sortedEntities) {
            int type = type1SearchEntity.getType1();
            //System.out.println("TYPE:"+type);
            preferSkus = type1SearchEntity.getPreferSkus();
            preferSkusMap.put(type, preferSkus);
            generalSkus = type1SearchEntity.getGeneralSkus();
            generalSkusMap.put(type, generalSkus);
          }
          //System.out.println("开始blend");
          List<VSKU> blendPreferList = BlenderUtils.blend(stgOrderMap, preferSkusMap, 2);
          List<VSKU> blendGeneralList = BlenderUtils.blend(stgOrderMap, generalSkusMap, 3);
          Set<Integer> isOrderSet = new HashSet<>();
          ///////////////////
          ///////////////////
          for (VSKU vsku : blendPreferList) {
            int lid = vsku.getId();
            if (!isOrderSet.contains(lid)) {
              isOrderSet.add(lid);
              vSKUResultList.add(vsku);
            }
          }
          for (VSKU vsku : blendGeneralList) {
            int lid = vsku.getId();
            if (!isOrderSet.contains(lid)) {
              isOrderSet.add(lid);
              vSKUResultList.add(vsku);
            }
          }
        }catch (Exception e){
          e.printStackTrace();
          ErrorLogger.logError(searchParameterOrigin, e);
          writeError(searchParameterOrigin, resp, beginTime, RESULT_PROCESSING_ERROR,
                     new BlendException("混排异常:"+e.getMessage()));
          return;
        }
        blend_size = vSKUResultList.size();

        try {
          List<VSKU> skus = ListUtils.ToSubList(vSKUResultList, p_start, p_end);
          SearchEntity _searchEntity = new SearchEntity(skus.size());
          _searchEntity.addSkus(skus);
          finalPackage = Lists.newArrayList(_searchEntity);
          vResult = getResullt(skus, blend_size);
        }catch (Exception e){
          e.printStackTrace();
          writeError(searchParameterOrigin, resp, beginTime, RESULT_PROCESSING_ERROR,
                     new BlendException("混排异常:" + e.getMessage()));
          return;
        }
        /////////////////////////---------------------------------------------------------////////////////////////////
      } else {
        try {
          //System.out.println("非混排");
          Map<Integer, VInnerResult> map = new HashMap<>();
          for (int i = 0; i < sortedEntities.size(); i++) {
            sortedEntities.get(i).sub(p_start, p_end);
            //System.out.println("stgtype:"+sortedEntities.get(i).getType1());
            map.put(sortedEntities.get(i).getType1(), sortedEntities.get(i).getMap(p_start, p_end));
          }
          finalPackage = sortedEntities;
          vResult = new VResult(map);
        }catch (Exception e){
          e.printStackTrace();
          System.out.println(e.toString());
        }
      }
      t6 = System.currentTimeMillis();
      //System.out.println("混排时间:"+(System.currentTimeMillis() - t6));
      //
    }else if(sort > 0 && sort < 5){
      //System.out.println("NEW sort:"+sort);
      if(count > 1){

        //System.out.println("new sort 线程池~~");
        //////////////////////////////////////////////////////////////////
        if(meta_data) {
          ExecutorService service = DeserializerThreadPoolHolder.getInstance().getService();
          List<Future<SearchEntity>> futures = Lists.newArrayListWithCapacity(count);
          List<String> stringList = null;
          List<AggregationProduct> aggList = Lists.newArrayListWithCapacity(count);
          //
          for (int i = 0; i < count; i++) {
            //long s1 = System.currentTimeMillis();
            if (i != count1) {
              stringList = sr_StringList
                .subList(i * Constants.SEARCH_THRESHOLD, (i + 1) * Constants.SEARCH_THRESHOLD);
            } else {
              stringList = sr_StringList.subList(i * Constants.SEARCH_THRESHOLD, searchResultSize);

            }
            //long s2 = System.currentTimeMillis();
            //System.out.println("循环时间:" + (s2 - s1));
            AggregationProduct agg = new AggregationProduct();
            CacheAllProcessor processor = new CacheAllProcessor(
              searchParameterOrigin, stringList, result_mode, filters, agg, regular, System.currentTimeMillis());
            aggList.add(agg);
            futures.add(service.submit(processor));
          }
          searchEntity = new SearchEntity();
          //System.out.println("new sort 获取结果");
          for (int i = 0; i < count; i++) {
            try {
              searchEntity.add(futures.get(i).get(1000, TimeUnit.MILLISECONDS));
              if (meta_data) {
                searchCensus.add(aggList.get(i));
              }
              //////////////////////////////////////////////////////////
            } catch (Exception e) {
              ErrorLogger.logError(searchParameterOrigin, e);
            }
          }
        }else {
          ExecutorService service = DeserializerThreadPoolHolder.getInstance().getService();
          List<Future<SearchEntity>> futures = Lists.newArrayListWithCapacity(count);
          List<String> stringList = null;
          List<Set<Integer>> aggList = Lists.newArrayListWithCapacity(count);
          //
          for (int i = 0; i < count; i++) {
            //long s1 = System.currentTimeMillis();
            if (i != count1) {
              stringList = sr_StringList
                .subList(i * Constants.SEARCH_THRESHOLD, (i + 1) * Constants.SEARCH_THRESHOLD);
            } else {
              stringList = sr_StringList.subList(i * Constants.SEARCH_THRESHOLD, searchResultSize);

            }
            //long s2 = System.currentTimeMillis();
            //System.out.println("循环时间:" + (s2 - s1));
            Set<Integer> agg = new HashSet<>();
            CacheAllNoMetaProcessor processor = new CacheAllNoMetaProcessor(
              searchParameterOrigin, stringList, result_mode, filters, agg, regular, System.currentTimeMillis());
            aggList.add(agg);
            futures.add(service.submit(processor));
          }
          searchEntity = new SearchEntity();
          //System.out.println("new sort 获取结果");
          for (int i = 0; i < count; i++) {
            try {
              searchEntity.add(futures.get(i).get(1000, TimeUnit.MILLISECONDS));
              if (!meta_data) {
                if(CollectionUtils.isNotEmpty(aggList.get(i)))
                  setStg.addAll(aggList.get(i));
              }
              //////////////////////////////////////////////////////////
            } catch (Exception e) {
              ErrorLogger.logError(searchParameterOrigin, e);
            }
          }
        }
      }else {
        if(meta_data) {
          searchEntity = ModelUtils
            .packageAllSTG(searchParameterOrigin, sr_StringList, filters, regular, searchCensus,
                           result_mode);
          /*if (CollectionUtils.isEmpty(filters)) {
            searchEntity = ModelUtils
              .packageAll(searchParameterOrigin, sr_StringList, null, regular, searchCensus,
                          result_mode);
          } else {
            searchEntity = ModelUtils
              .packageAll(searchParameterOrigin, sr_StringList, filters, regular, searchCensus,
                          result_mode);
          }*/
        }else {
          searchEntity = ModelUtils
            .packageAllSTG(searchParameterOrigin, sr_StringList, filters, regular, setStg,
                        result_mode);
          /*if (CollectionUtils.isEmpty(filters)) {
            searchEntity = ModelUtils
              .packageAll(searchParameterOrigin, sr_StringList, null, regular, setStg,
                          result_mode);
          } else {
            searchEntity = ModelUtils
              .packageAll(searchParameterOrigin, sr_StringList, filters, regular, setStg,
                          result_mode);
          }*/
        }
      }
      //排序
      t5 = System.currentTimeMillis();
      //t6 = t5;
      transformMergeResultTime = t5 - t4;
      //System.out.println("SORT反序列化时间:"+transformMergeResultTime);

      Map<Integer, Integer> order_map = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                  .getvStypeMap()
                                                                                  .get(channel)
                                                                                  .getOrder_STG();
      if(meta_data)
        prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, searchCensus);
      else
        prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, setStg);

      if(sort == 1){
        try {
          //long s1 = System.currentTimeMillis();
          //finalPackage = new VSalesSorter(searchParameterOrigin, searchEntity, 0, p_start, p_end).sort();
          //long s2 = System.currentTimeMillis();
          //System.out.println("old sort " + (s2 - s1));
          strategy = "sup";
          finalPackage = new VSalesTimSorterNoMarket2(searchParameterOrigin, searchEntity, 0, p_start, p_end).sort();
          //long s3 = System.currentTimeMillis();
          //System.out.println("new sort " + (s3 - s2));
          if(CollectionUtils.isNotEmpty(finalPackage)) {
            if(CollectionUtils.isNotEmpty(searchParameterOrigin.getType1s()) && (searchParameterOrigin.getType1s().size() == 1)){
              int stg = -1;
              for(int stgId:searchParameterOrigin.getType1s()){
                stg = stgId;
              }
              vResult = getResullt(finalPackage.get(0), stg);
            }else {
              vResult = getResullt(finalPackage.get(0));
            }
          }
          else
            vResult = null;
          //System.out.println("after sort:"+finalPackage.get(0).getIdSet());
          //WarningLogger.logWarning("sort:1", searchParameterOrigin, null);
        } catch (Exception e){
          logWarning("Sorting failed", searchParameterOrigin, e);
          e.printStackTrace();
          finalPackage = Lists.newArrayList(searchEntity);
        }

      }else if(sort == 2){
        try {
          //long s1 = System.currentTimeMillis();
          //finalPackage = new VSalesSorter(searchParameterOrigin, searchEntity, 1, p_start, p_end).sort();
          //long s2 = System.currentTimeMillis();
          //System.out.println("old sort ");
          strategy = "sdown";
          finalPackage = new VSalesTimSorterNoMarket2(searchParameterOrigin, searchEntity, 1, p_start, p_end).sort();
          //long s3 = System.currentTimeMillis();
          //System.out.println("new sort " + (s3 - s2));
          if(CollectionUtils.isNotEmpty(finalPackage)) {
            if(CollectionUtils.isNotEmpty(searchParameterOrigin.getType1s()) && (searchParameterOrigin.getType1s().size() == 1)){
              int stg = -1;
              for(int stgId:searchParameterOrigin.getType1s()){
                stg = stgId;
              }
              vResult = getResullt(finalPackage.get(0), stg);
            }else {
              vResult = getResullt(finalPackage.get(0));
            }
          }
          else
            vResult = null;
          //System.out.println("after sort:"+finalPackage.get(0).getIdSet());
          //WarningLogger.logWarning("sort:2", searchParameterOrigin, null);
        } catch (Exception e) {
          e.printStackTrace();
          logWarning("Sorting failed", searchParameterOrigin, e);
          finalPackage = Lists.newArrayList(searchEntity);
        }
      }else if(sort == 3){
        try {
          //long s1 = System.currentTimeMillis();
          //finalPackage = new VPriceSorter(searchParameterOrigin, searchEntity, 0, p_start, p_end).sort();
          //long s2 = System.currentTimeMillis();
          //System.out.println("old sort " + (s2 - s1));
          strategy = "pup";
          finalPackage = new VPriceTimSorterNoMarket2(searchParameterOrigin, searchEntity, 0, p_start, p_end).sort();
          //long s3 = System.currentTimeMillis();
          //System.out.println("new sort " + (s3 - s2));
          if(CollectionUtils.isNotEmpty(finalPackage)) {
            if(CollectionUtils.isNotEmpty(searchParameterOrigin.getType1s()) && (searchParameterOrigin.getType1s().size() == 1)){
              int stg = -1;
              for(int stgId:searchParameterOrigin.getType1s()){
                stg = stgId;
              }
              vResult = getResullt(finalPackage.get(0), stg);
            }else {
              vResult = getResullt(finalPackage.get(0));
            }
          }
          else
            vResult = null;
          //System.out.println("after sort:"+finalPackage.get(0).getIdSet());
          //WarningLogger.logWarning("sort:3", searchParameterOrigin, null);
        }catch (Exception e){
          e.printStackTrace();
          logWarning("Sorting failed", searchParameterOrigin, e);
          finalPackage = Lists.newArrayList(searchEntity);
        }

      }else if(sort == 4){
        try {
          //long s1 = System.currentTimeMillis();
          //finalPackage = new VPriceSorter(searchParameterOrigin, searchEntity, 1, p_start, p_end).sort();
          //long s2 = System.currentTimeMillis();
          //System.out.println("old sort " + (s2 - s1));
          strategy = "pdown";
          finalPackage = new VPriceTimSorterNoMarket2(searchParameterOrigin, searchEntity, 1, p_start, p_end).sort();
          //ong s3 = System.currentTimeMillis();
          //System.out.println("new sort " + (s3 - s2));
          if(CollectionUtils.isNotEmpty(finalPackage)) {
            if(CollectionUtils.isNotEmpty(searchParameterOrigin.getType1s()) && (searchParameterOrigin.getType1s().size() == 1)){
              int stg = -1;
              for(int stgId:searchParameterOrigin.getType1s()){
                stg = stgId;
              }
              vResult = getResullt(finalPackage.get(0), stg);
            }else {
              vResult = getResullt(finalPackage.get(0));
            }
          }
          else
            vResult = null;
          //System.out.println("after sort:"+finalPackage.get(0).getIdSet());
          //WarningLogger.logWarning("sort:4", searchParameterOrigin, null);
        }catch (Exception e){
          e.printStackTrace();
          logWarning("Sorting failed", searchParameterOrigin, e);
          finalPackage = Lists.newArrayList(searchEntity);
        }
      }
      //
      t6 = System.currentTimeMillis();
    }else{
      //error
      writeError(searchParameterOrigin, resp, beginTime, INVALID_PARAMETER, null);
      return;
    }
    t7 = System.currentTimeMillis();
    searchFilterInfo = null;
    try {
      if(CollectionUtils.isEmpty(finalPackage))
        finalPackage = new ArrayList<>();
      SearchReportItem sri = new SearchReportItem(searchParameterOrigin, transfer(finalPackage));
      TimeCost tc = new TimeCost(t2 - t1, t3 - t2, t4 - t3, transformMergeResultTime, t6 - t5, t7 - beginTime).addTime("blend-result", t7 - t6);
      //修正
      report(sri, tc);

      Map<Integer, Integer> order_map = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                  .getvStypeMap()
                                                                                  .get(channel)
                                                                                  .getOrder_STG();
      //List<Integer> stgOr = new ArrayList<>();
      //Prefer prefer = getPrefer(stgOr, order_map, preSKUType1, preSKUType2, searchCensus);
      Intention intention = new Intention(prefer, segmentation);
      if(meta_data) {
        searchCensus.sort();
        searchFilterInfo = new SearchFilterInfo(searchCensus.getStg_info(), stgOr, intention);
      }else {
        searchFilterInfo = null;
      }
      /*if(!meta_data){
        searchFilterInfo = null;
      }*/
    }catch (Exception e){
      e.printStackTrace();
      System.out.println(e.toString());
    }

    //System.out.println("执行时间:" + new DateTime().toString());

    if (onlyData) {
      writeOK(resp, beginTime, searchParameterOrigin.getRequestId(), strategy, vResult,
              searchFilterInfo);
    } else {
      //临时增加
      List<BlenderLayoutPattern<Integer>> blenderLayoutPatternList = new ArrayList<>();
      Set<Integer> s_type_group = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                            .getvStypeMap()
                                                                            .get(channel)
                                                                            .getS_type_group_set();
      for(int stgId:s_type_group){
        blenderLayoutPatternList.add(new BlenderLayoutPattern<Integer>(stgId));
      }
      doRenderPage(resp, searchParameterOrigin, tuples, finalPackage, t5 - beginTime,
                   resp.getWriter(), useSimpleResult, blendAll, blenderLayoutPatternList,
                   startTimeShow, limitStr);
    }

  }

  private void doRenderPage(HttpServletResponse resp, SearchParameterEntity searchParameter,
                            Set<List<Word>> tuples, List<? extends SearchEntity> packages,
                            long requestTime, Writer writer, boolean useSimpleResult,
                            boolean blendResult,
                            List<BlenderLayoutPattern<Integer>> blendLayouts, String startTimeShow, String limit) throws IOException {
    VMTemplate.getInstance().mergeSearchResult2(searchParameter, tuples, packages, requestTime,
                                                this, resp.getWriter(), useSimpleResult,
                                                blendResult, blendLayouts, startTimeShow);
    writer.flush();
  }

  private List<Segment> getIntention2(SearchParameterEntity searchParameterOrigin, Set<List<Word>> tuples,
                                      Set<Integer> preSKUType1, Set<Integer> preSKUType2, int channel){
    boolean canDefinDest = true;
    int n_Continent = 0;
    int n_Country = 0;
    int n_City = 0;
    Word wordCon = null;
    Word wordCou = null;
    Word wordCit = null;
    List<Segment> segmentation = new ArrayList<>();
    ZTagEntity zTagEntity = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap().get(
      channel);
    Map<String, Integer> cityInfoMap = MutableCaches.getInstance().CITIES.getCacheContent();
    Map<Integer, Set<Integer>> areaSet = MutableCaches.getInstance().AREA_CITY_MAP.getCacheContent();


    Set<Integer> stype = new HashSet<>();
    Set<Integer> stypegroup = new HashSet<>();
    Set<Integer> tagsPrefer = new HashSet<>();
    if(tuples.size() == 1){
      for(List<Word> list:tuples){
        if(list.size() == 1) {
          String name = list.get(0).getName();
          String avatar = Constants.SPECIAL_PREFER.get(name);
          //System.out.println("word name:"+name);
          /////国内城市为目的地，需要修改
          if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(name)){
            searchParameterOrigin.reconstructWithCity(name);
            //tuples = new HashSet<>();
            tuples.clear();
            if(cityInfoMap.containsKey(name)) {
              int IdForCity = cityInfoMap.get(name);
              Segment segment = new Segment(name, "city", IdForCity);

              if(areaSet.containsKey(IdForCity)){
                segment.setCtype("area");
              }else {
                segment.setCtype("city");
              }
              segmentation.add(segment);
            }
          }else if(MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().containsKey(name)){
            searchParameterOrigin.reconstructWithCountry(list.get(0).getName());
            //tuples = new HashSet<>();
            tuples.clear();
            Segment segment = new Segment(name, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().get(name).intValue());
            segmentation.add(segment);
          } else if(zTagEntity.getS_type_group_map().containsKey(name)){
            preSKUType1.add(zTagEntity.getS_type_group_map().get(name));
          }else if(zTagEntity.getS_type_map().containsKey(name)){
            preSKUType2.add(zTagEntity.getS_type_map().get(name));
            preSKUType1.addAll(
              zTagEntity.getNegativeMap().get(zTagEntity.getS_type_map().get(name)));
          }else if(Constants.CONTINENT_MAP.containsKey(name)){
            //System.out.println("set continent");
            searchParameterOrigin.setContinentIf(name);
            tuples.clear();
            //System.out.println("after set continent:"+searchParameterOrigin.getContinent());
          }else if(StringUtils.isNotEmpty(avatar) && zTagEntity.getS_type_group_map().containsKey(avatar)) {
            preSKUType1.add(zTagEntity.getS_type_group_map().get(avatar));
            System.out.println("preSKUType1:"+preSKUType1);
          }else if(StringUtils.isNotEmpty(avatar) && zTagEntity.getS_type_map().containsKey(avatar)){
            preSKUType2.add(zTagEntity.getS_type_map().get(avatar));
            preSKUType1.addAll(
              zTagEntity.getNegativeMap().get(zTagEntity.getS_type_map().get(avatar)));
          } else if(Impression.TAGS == list.get(0).getFirstImpression()){
            preSKUType1.add(Constants.TAGS_PREFER.get(channel));
          }else if(Impression.IMPRESSION_POI == list.get(0).getFirstImpression()){
            preSKUType1.add(Constants.TAGS_PREFER.get(channel));
          }
        }else {
          for(Word word: list){
            String name = word.getName();

            /*if(zTagEntity.getS_type_map().containsKey(name)){
              stype.add(zTagEntity.getS_type_map().get(name));
            }
            if(zTagEntity.getS_type_group_map().containsKey(name)){
              stypegroup.add(zTagEntity.getS_type_group_map().get(name));
            }*/

            if(zTagEntity.getS_type_map().containsKey(name) || zTagEntity.getS_type_group_map().containsKey(name)){
              if(zTagEntity.getS_type_map().containsKey(name)){
                stype.add(zTagEntity.getS_type_map().get(name));
              }
              if(zTagEntity.getS_type_group_map().containsKey(name)){
                stypegroup.add(zTagEntity.getS_type_group_map().get(name));
              }
            }else {
              if(Impression.TAGS == word.getFirstImpression()){
                tagsPrefer.add(Constants.TAGS_PREFER.get(channel));
              }else if(Impression.IMPRESSION_POI == word.getFirstImpression()){
                tagsPrefer.add(Constants.TAGS_PREFER.get(channel));
              }
            }

            //确定目的地
            if(canDefinDest) {
              if ((word.getFirstImpression() == Impression.IMPRESSION_CONTINENT)
                ||MutableCaches.getInstance().CONTINENT_DICT.getCacheContent().getReverseDict().containsKey(name)) {
              //if ((word.getFirstImpression() == Impression.IMPRESSION_CONTINENT)||Constants.CONTINENT_MAP.containsKey(name)) {
                //System.out.println("大洲:"+ name);
                if (++n_Continent > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCon = word;
                }
              }else if(word.getFirstImpression() == Impression.IMPRESSION_COUNTRY||MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().containsKey(name)){
                //System.out.println("国家识别~");
                if (++n_Country > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCou = word;
                }
              }else if(word.getFirstImpression() == Impression.IMPRESSION_CITY){
                //System.out.println("城市识别~");
                if (++n_City > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCit = word;
                }
              }
            }
          }
          //判断是否确定意图，未来会有新的逻辑，比如优先级
          if((stype.size() <= 1)&&(stypegroup.size() <= 1)){
            if(stypegroup.size() == 1){
              for(int j:stypegroup) {
                //System.out.println("j:"+j);
                if (stype.size() == 1) {
                  for (int jk : stype) {
                    if (zTagEntity.getNegativeMap().get(jk).contains(j)){
                      preSKUType1.add(j);
                      preSKUType2.add(jk);
                      //System.out.println("jk:"+jk);
                    }
                  }
                }else {
                  preSKUType1.add(j);
                }
              }
            }else if(stype.size() == 1){
              for (int jk : stype) {
                preSKUType2.add(jk);
                //System.out.println("jk:" + jk);
                List<Integer> stgList = zTagEntity.getNegativeMap().get(jk);
                if(CollectionUtils.isNotEmpty(stgList)){
                  preSKUType1.addAll(stgList);
                }
              }
            }else if(tagsPrefer.size() == 1){
              for(int ptg:tagsPrefer)
                preSKUType1.add(ptg);
            }
          }

          //是否一个地方
          if(canDefinDest){
            if((n_City + n_Country + n_Continent) > 1){
              if(wordCit == null){
                String _country = wordCou.getName();
                String _continent = wordCon.getName();
                //System.out.println("城市为空:" + "国家:"+_country + "：大洲:"+_continent);
                if(_continent.equals(MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country))){
                  if(searchParameterOrigin.isCountryAbsent()) {
                    if(MutableCaches.getInstance().OVERSEA_COUNTRIES
                      .getCacheContent().containsKey(_country)) {
                      Segment segment = new Segment(_country, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES
                        .getCacheContent().get(_country));
                      segmentation.add(segment);
                    }
                  }
                  searchParameterOrigin.setDestCountryIf(_country);
                  searchParameterOrigin.setContinentIf(_continent);
                  list.remove(wordCon);
                  list.remove(wordCou);
                  if(CollectionUtils.isEmpty(list)){
                    tuples.clear();
                  }
                }
              }else if(wordCou == null){
                String _city = wordCit.getName();
                String _continent = wordCon.getName();
                //System.out.println("国家为空:" + "国家:"+_city + "：大洲:"+_continent);
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(_city);
                if(CollectionUtils.isNotEmpty(_countryList)){
                  for(String _country : _countryList){
                    String continent1 = MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country);
                    if(_continent.equals(continent1)){
                      //小bug
                      if(searchParameterOrigin.isCityAbsent()){
                        if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                          if(cityInfoMap.containsKey(_city)) {
                            int IdForCity = cityInfoMap.get(_city);
                            Segment segment = new Segment(_city, "city", IdForCity);
                            if(areaSet.containsKey(IdForCity)){
                              segment.setCtype("area");
                            }else {
                              segment.setCtype("city");
                            }
                            segmentation.add(segment);
                          }
                        }
                      }
                      searchParameterOrigin.setDestCountryIf(_country);
                      searchParameterOrigin.setDestIf(_city);
                      searchParameterOrigin.setContinentIf(_continent);
                      list.remove(wordCon);
                      list.remove(wordCit);
                      if(CollectionUtils.isEmpty(list)){
                        tuples.clear();
                      }
                    }
                  }
                }
              }else if(wordCon == null){
                //System.out.println("大洲为空");
                String _city = wordCit.getName();
                String _country = wordCou.getName();
                //System.out.println("大洲为空:" + "国家:"+_city + "：国家:"+_country);
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(
                  _city);
                if(CollectionUtils.isNotEmpty(_countryList)) {
                  for (String str : _countryList) {
                    if(_country.equals(str)){
                      if(searchParameterOrigin.isCityAbsent()){
                        if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                          if(cityInfoMap.containsKey(_city)) {
                            int IdForCity = cityInfoMap.get(_city);
                            Segment segment = new Segment(_city, "city", IdForCity);
                            if(areaSet.containsKey(IdForCity)){
                              segment.setCtype("area");
                            }else {
                              segment.setCtype("city");
                            }
                            segmentation.add(segment);
                          }
                        }
                      }
                      searchParameterOrigin.setDestCountryIf(_country);
                      searchParameterOrigin.setDestIf(_city);
                      list.remove(wordCit);
                      list.remove(wordCou);
                      if(CollectionUtils.isEmpty(list)){
                        tuples.clear();
                      }
                    }
                  }
                }
              }else {
                String _city = wordCit.getName();
                String _country = wordCou.getName();
                String _continent = wordCon.getName();
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(_city);
                if(_continent.equals(MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country))) {
                  if (CollectionUtils.isNotEmpty(_countryList)) {
                    for (String str : _countryList) {
                      if (_country.equals(str)) {
                        if(searchParameterOrigin.isCityAbsent()){
                          if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                            if(cityInfoMap.containsKey(_city)) {
                              int IdForCity = cityInfoMap.get(_city);
                              Segment segment = new Segment(_city, "city", IdForCity);
                              if(areaSet.containsKey(IdForCity)){
                                segment.setCtype("area");
                              }else {
                                segment.setCtype("city");
                              }
                              segmentation.add(segment);
                            }
                          }
                        }
                        searchParameterOrigin.setDestIf(_city);
                        searchParameterOrigin.setDestCountryIf(_country);
                        searchParameterOrigin.setContinentIf(_continent);
                        list.remove(wordCit);
                        list.remove(wordCou);
                        list.remove(wordCon);
                        if(CollectionUtils.isEmpty(list)){
                          tuples.clear();
                        }
                      }
                    }
                  }
                }
              }
            }else if(n_City == 1){
              String _city = wordCit.getName();
              //System.out.println("city:"+_city);
              if(MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().containsKey(_city)){
                //if(MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().containsKey(_city)){
                if(searchParameterOrigin.isCityAbsent()){
                  if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                    if(cityInfoMap.containsKey(_city)) {
                      int IdForCity = cityInfoMap.get(_city);
                      Segment segment = new Segment(_city, "city", IdForCity);
                      if(areaSet.containsKey(IdForCity)){
                        segment.setCtype("area");
                      }else {
                        segment.setCtype("city");
                      }
                      segmentation.add(segment);
                    }
                  }
                }
                searchParameterOrigin.reconstructWithCity(_city);
                list.remove(wordCit);
              }else if(MutableCaches.getInstance().TAIWAN_MAP.getCacheContent().contains(_city)){
                if(searchParameterOrigin.isCityAbsent()){
                  if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                    if(cityInfoMap.containsKey(_city)) {
                      int IdForCity = cityInfoMap.get(_city);
                      Segment segment = new Segment(_city, "city", IdForCity);
                      if(areaSet.containsKey(IdForCity)){
                        segment.setCtype("area");
                      }else {
                        segment.setCtype("city");
                      }
                      segmentation.add(segment);
                    }
                  }
                }
                searchParameterOrigin.reconstructWithCity(_city);
                list.remove(wordCit);
              }
            }else if(n_Country == 1){
              String _country = wordCou.getName();
              if(searchParameterOrigin.isCountryAbsent()) {
                if(MutableCaches.getInstance().OVERSEA_COUNTRIES
                  .getCacheContent().containsKey(_country)) {
                  Segment segment = new Segment(_country, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES
                    .getCacheContent().get(_country));
                  segmentation.add(segment);
                }
              }
              searchParameterOrigin.setDestCountryIf(_country);
              list.remove(wordCou);
            }else if(n_Continent == 1){
              searchParameterOrigin.setContinentIf(wordCon.getName());
              list.remove(wordCon);
            }
          }
        }
      }
    }else{
      /*for(List<Word> list: tuples){
        for(Word word: list){
          if(Constants.HOT_PS_1.containsKey(word.getName())){
            preSKUType1.add(Constants.HOT_PS_1.get(word.getName()));
          }else if(Constants.HOT_PS_2.containsKey(word.getName())){
            preSKUType2.add(Constants.HOT_PS_2.get(word.getName()));
          }
          //确定目的地
        }
      }*/
    }

    return segmentation;
  }

  private List<Segment> getIntention3(SearchParameterEntity searchParameterOrigin, Set<List<Word>> tuples,
                                      Set<Integer> preSKUType1, Set<Integer> preSKUType2, int channel){
    boolean canDefinDest = true;
    int n_Continent = 0;
    int n_Country = 0;
    int n_City = 0;
    Word wordCon = null;
    Word wordCou = null;
    Word wordCit = null;
    List<Segment> segmentation = new ArrayList<>();
    ZTagEntity zTagEntity = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap().get(
      channel);
    Map<String, Integer> cityInfoMap = MutableCaches.getInstance().CITIES.getCacheContent();

    Set<Integer> stype = new HashSet<>();
    Set<Integer> stypegroup = new HashSet<>();
    if(tuples.size() == 1){
      for(List<Word> list:tuples){
        if(list.size() == 1) {
          String name = list.get(0).getName();
          //System.out.println("word name:"+name);
          /////国内城市为目的地，需要修改
          if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(name)){
            searchParameterOrigin.reconstructWithCity(name);
            tuples = new HashSet<>();
            if(cityInfoMap.containsKey(name)) {
              Segment segment = new Segment(name, "city", cityInfoMap.get(name));
              segmentation.add(segment);
            }
          }else if(MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().containsKey(name)){
            searchParameterOrigin.reconstructWithCountry(list.get(0).getName());
            tuples = new HashSet<>();
            Segment segment = new Segment(name, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().get(name).intValue());
            segmentation.add(segment);
          } else if(zTagEntity.getS_type_group_map().containsKey(name)){
            preSKUType1.add(zTagEntity.getS_type_group_map().get(name));
          }else if(zTagEntity.getS_type_map().containsKey(name)){
            preSKUType2.add(zTagEntity.getS_type_map().get(name));
            preSKUType1.addAll(
              zTagEntity.getNegativeMap().get(zTagEntity.getS_type_map().get(name)));
          }else if(Constants.CONTINENT_MAP.containsKey(name)){
            System.out.println("set continent");
            searchParameterOrigin.setContinent(name);
            System.out.println("after set continent:" + searchParameterOrigin.getContinent());
          }
        }else {
          for(Word word: list){
            String name = word.getName();
            System.out.println("Word Name:" + name);
            if(zTagEntity.getS_type_map().containsKey(name)){
              System.out.println("stype name:" + name);
              stype.add(zTagEntity.getS_type_map().get(name));
            }
            if(zTagEntity.getS_type_group_map().containsKey(name)){
              System.out.println("sgtype name:" + name);
              stypegroup.add(zTagEntity.getS_type_group_map().get(name));
            }
            //确定目的地
            if(canDefinDest) {
              if ((word.getFirstImpression() == Impression.IMPRESSION_CONTINENT)||Constants.CONTINENT_MAP.containsKey(name)) {
                //System.out.println("大洲");
                if (++n_Continent > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCon = word;
                }
              }else if(word.getFirstImpression() == Impression.IMPRESSION_COUNTRY||MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().containsKey(name)){
                System.out.println("国家识别~");
                if (++n_Country > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCou = word;
                }
              }else if(word.getFirstImpression() == Impression.IMPRESSION_CITY){
                System.out.println("城市识别~");
                if (++n_City > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCit = word;
                }
              }
            }
          }
          //判断是否确定意图，未来会有新的逻辑，比如优先级
          if((stype.size() <= 1)&&(stypegroup.size() <= 1)){
            if(stypegroup.size() == 1){
              for(int j:stypegroup) {
                System.out.println("j:"+j);
                if (stype.size() == 1) {
                  for (int jk : stype) {
                    if (zTagEntity.getNegativeMap().get(jk).contains(j)){
                      preSKUType1.add(j);
                      preSKUType2.add(jk);
                      System.out.println("jk:"+jk);
                    }
                  }
                }else {
                  preSKUType1.add(j);
                }
              }
            }else {
              for (int jk : stype) {
                preSKUType2.add(jk);
                System.out.println("jk:" + jk);
                List<Integer> stgList = zTagEntity.getNegativeMap().get(jk);
                if(CollectionUtils.isNotEmpty(stgList)){
                  preSKUType1.addAll(stgList);
                }
              }
            }
          }

          //是否一个地方
          if(canDefinDest){
            if((n_City + n_Country + n_Continent) > 1){
              if(wordCit == null){
                String _country = wordCou.getName();
                String _continent = wordCon.getName();
                //System.out.println("城市为空:" + "国家:"+_country + "：大洲:"+_continent);
                if(_continent.equals(MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country))){
                  if(searchParameterOrigin.isCountryAbsent()) {
                    if(MutableCaches.getInstance().OVERSEA_COUNTRIES
                      .getCacheContent().containsKey(_country)) {
                      Segment segment = new Segment(_country, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES
                        .getCacheContent().get(_country));
                      segmentation.add(segment);
                    }
                  }
                  searchParameterOrigin.setDestCountryIf(_country);
                  searchParameterOrigin.setContinent(_continent);
                  list.remove(wordCon);
                  list.remove(wordCou);
                  if(CollectionUtils.isEmpty(list)){
                    tuples.clear();
                  }
                }
              }else if(wordCou == null){
                String _city = wordCit.getName();
                String _continent = wordCon.getName();
                //System.out.println("国家为空:" + "国家:"+_city + "：大洲:"+_continent);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(_city);
                if(CollectionUtils.isNotEmpty(_countryList)){
                  for(String _country : _countryList){
                    String continent1 = MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country);
                    if(_continent.equals(continent1)){
                      //小bug
                      if(searchParameterOrigin.isCityAbsent()){
                        if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                          if(cityInfoMap.containsKey(_city)) {
                            Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                            segmentation.add(segment);
                          }
                        }
                      }
                      searchParameterOrigin.setDestCountryIf(_country);
                      searchParameterOrigin.setDestIf(_city);
                      list.remove(wordCon);
                      list.remove(wordCit);
                      if(CollectionUtils.isEmpty(list)){
                        tuples.clear();
                      }
                    }
                  }
                }
              }else if(wordCon == null){
                //System.out.println("大洲为空");
                String _city = wordCit.getName();
                String _country = wordCou.getName();
                //System.out.println("大洲为空:" + "国家:"+_city + "：国家:"+_country);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(_city);
                if(CollectionUtils.isNotEmpty(_countryList)) {
                  for (String str : _countryList) {
                    if(_country.equals(str)){
                      if(searchParameterOrigin.isCityAbsent()){
                        if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                          if(cityInfoMap.containsKey(_city)) {
                            Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                            segmentation.add(segment);
                          }
                        }
                      }
                      searchParameterOrigin.setDestCountryIf(_country);
                      searchParameterOrigin.setDestIf(_city);
                      list.remove(wordCit);
                      list.remove(wordCou);
                      if(CollectionUtils.isEmpty(list)){
                        tuples.clear();
                      }
                    }
                  }
                }
              }else {
                String _city = wordCit.getName();
                String _country = wordCou.getName();
                String _continent = wordCon.getName();
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(_city);
                if(_continent.equals(MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country))) {
                  if (CollectionUtils.isNotEmpty(_countryList)) {
                    for (String str : _countryList) {
                      if (_country.equals(str)) {
                        if(searchParameterOrigin.isCityAbsent()){
                          if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                            if(cityInfoMap.containsKey(_city)) {
                              Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                              segmentation.add(segment);
                            }
                          }
                        }
                        searchParameterOrigin.setDestIf(_city);
                        searchParameterOrigin.setDestCountryIf(_country);
                        list.remove(wordCit);
                        list.remove(wordCou);
                        list.remove(wordCon);
                        if(CollectionUtils.isEmpty(list)){
                          tuples.clear();
                        }
                      }
                    }
                  }
                }
              }
            }else if(n_City == 1){
              String _city = wordCit.getName();
              if(MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().containsKey(_city)){
                //if(MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().containsKey(_city)){
                if(searchParameterOrigin.isCityAbsent()){
                  if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                    if(cityInfoMap.containsKey(_city)) {
                      Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                      segmentation.add(segment);
                    }
                  }
                }
                searchParameterOrigin.reconstructWithCity(_city);
                list.remove(wordCit);
              }else if(MutableCaches.getInstance().TAIWAN_MAP.getCacheContent().contains(_city)){
                if(searchParameterOrigin.isCityAbsent()){
                  if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                    if(cityInfoMap.containsKey(_city)) {
                      Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                      segmentation.add(segment);
                    }
                  }
                }
                searchParameterOrigin.reconstructWithCity(_city);
                list.remove(wordCit);
              }
            }else if(n_Country == 1){
              String _country = wordCou.getName();
              if(searchParameterOrigin.isCountryAbsent()) {
                if(MutableCaches.getInstance().OVERSEA_COUNTRIES
                  .getCacheContent().containsKey(_country)) {
                  Segment segment = new Segment(_country, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES
                    .getCacheContent().get(_country));
                  segmentation.add(segment);
                }
              }
              searchParameterOrigin.setDestCountryIf(_country);
              list.remove(wordCou);
            }else if(n_Continent == 1){
              searchParameterOrigin.setContinent(wordCon.getName());
            }
          }
        }
      }
    }else{
      /*for(List<Word> list: tuples){
        for(Word word: list){
          if(Constants.HOT_PS_1.containsKey(word.getName())){
            preSKUType1.add(Constants.HOT_PS_1.get(word.getName()));
          }else if(Constants.HOT_PS_2.containsKey(word.getName())){
            preSKUType2.add(Constants.HOT_PS_2.get(word.getName()));
          }
          //确定目的地
        }
      }*/
    }

    return segmentation;
  }

  //
  private VResult getResullt(List<VSKU> vskus, int size){
    if(CollectionUtils.isEmpty(vskus))
      return null;
    List<Integer> list = new ArrayList<>();
    for(VSKU vsku:vskus){
      list.add(vsku.getId());
    }
    VInnerResult vInnerResult = new VInnerResult(size, list);
    Map<Integer, VInnerResult> map = new HashMap<>();
    map.put(-1, vInnerResult);
    return new VResult(map);
  }

  private VResult getResullt(List<VSKU> vskus, int size, int stg){
    if(CollectionUtils.isEmpty(vskus))
      return null;
    List<Integer> list = Lists.newArrayListWithCapacity(vskus.size());
    for(VSKU vsku:vskus){
      list.add(vsku.getId());
    }
    VInnerResult vInnerResult = new VInnerResult(size, list);
    Map<Integer, VInnerResult> map = new HashMap<>();
    map.put(stg, vInnerResult);
    return new VResult(map);
  }
  private VResult getResullt(SearchEntity searchEntity){
    if(searchEntity == null)
      return null;
    return getResullt(searchEntity.getSkus(), searchEntity.getPackageSize());
  }

  private VResult getResullt(SearchEntity searchEntity, int stg){
    if(searchEntity == null)
      return null;
    return getResullt(searchEntity.getSkus(), searchEntity.getPackageSize(), stg);
  }

  private List<SearchPackage> transfer(List<? extends SearchEntity> entities){
    if(CollectionUtils.isEmpty(entities))
      return new ArrayList<>();
    List<SearchPackage> searchPackages = new ArrayList<>();
    for(int i = 0; i < entities.size(); i++){
      SearchEntity entity = entities.get(i);
      searchPackages.add(entity.toSP());
    }
    return searchPackages;
  }



  private Prefer getPrefer(Set<Integer> s1, Set<Integer> s2){
    int a = -1;
    int b = -1;
    if(CollectionUtils.isNotEmpty(s1)){
      for(int aa:s1){
        a = aa;
      }
    }

    if(CollectionUtils.isNotEmpty(s2)){
      for(int bb:s2){
        b = bb;
      }
    }
    return new Prefer(a, b);
  }

  private Prefer getPrefer(List<Integer> stgOrder, Map<Integer, Integer> meta, Set<Integer> s1,
                           Set<Integer> s2, AggregationProduct product){
    int aa = 11111;
    int b = -1;
    boolean isGet = false;
    Map<Integer, Integer> sortIntention = new TreeMap<>();
    Set<Integer> set = product.getStg_info().keySet();
    Set<Integer> setTest = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap().get(4).getS_type_group_set();
    //System.out.println("channel set:"+set);
    //System.out.println("meta set:" + meta);
    Set<Integer> set1 = new HashSet<>(set);
    if(CollectionUtils.isNotEmpty(s1)){
      for(int stgId:s1){
        int c = meta.get(stgId);
        if(c < aa) {
          aa = c;
          b = stgId;
        }
        sortIntention.put(c, stgId);
      }
    }
    Map<Integer, Integer> sort2 = new TreeMap<>();
    for(Map.Entry<Integer,Integer> m:meta.entrySet()){
      if(!s1.contains(m.getKey()))
        sort2.put(m.getValue(),m.getKey());
    }
    for(Map.Entry<Integer,Integer> m:sortIntention.entrySet()){
      if(set.contains(m.getValue())){
        stgOrder.add(m.getValue());
      }
    }

    for(Map.Entry<Integer,Integer> m:sort2.entrySet()){
      if(set.contains(m.getValue())){
        stgOrder.add(m.getValue());
      }
    }
    if(b < 0)
      return null;
    else{
      int cc = 0;
      if(CollectionUtils.isNotEmpty(s2)){
        for(int tmp:s2)
          cc = tmp;
        return new Prefer(b, cc);
      }else {
        return new Prefer(b);
      }
    }
  }


  private Prefer getPrefer(List<Integer> stgOrder, Map<Integer, Integer> meta, Set<Integer> s1,
                           Set<Integer> s2, Set<Integer> stgSet){
    int aa = 11111;
    int b = -1;
    boolean isGet = false;
    Map<Integer, Integer> sortIntention = new TreeMap<>();
    Set<Integer> set = stgSet;
    Set<Integer> setTest = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap().get(4).getS_type_group_set();
    //System.out.println("channel set:"+set);
    //System.out.println("meta set:" + meta);
    Set<Integer> set1 = new HashSet<>(set);
    if(CollectionUtils.isNotEmpty(s1)){
      for(int stgId:s1){
        int c = meta.get(stgId);
        if(c < aa) {
          aa = c;
          b = stgId;
        }
        sortIntention.put(c, stgId);
      }
    }
    Map<Integer, Integer> sort2 = new TreeMap<>();
    for(Map.Entry<Integer,Integer> m:meta.entrySet()){
      if(!s1.contains(m.getKey()))
        sort2.put(m.getValue(),m.getKey());
    }
    for(Map.Entry<Integer,Integer> m:sortIntention.entrySet()){
      if(set.contains(m.getValue())){
        stgOrder.add(m.getValue());
      }
    }

    for(Map.Entry<Integer,Integer> m:sort2.entrySet()){
      if(set.contains(m.getValue())){
        stgOrder.add(m.getValue());
      }
    }
    if(b < 0)
      return null;
    else{
      int cc = 0;
      if(CollectionUtils.isNotEmpty(s2)){
        for(int tmp:s2)
          cc = tmp;
        return new Prefer(b, cc);
      }else {
        return new Prefer(b);
      }
    }
  }





  private List<Segment> getIntention4(SearchParameterEntity searchParameterOrigin, Set<List<Word>> tuples,
                                      Set<Integer> preSKUType1, Set<Integer> preSKUType2, int channel){
    boolean canDefinDest = true;
    int n_Continent = 0;
    int n_Country = 0;
    int n_City = 0;
    Word wordCon = null;
    Word wordCou = null;
    Word wordCit = null;
    List<Segment> segmentation = new ArrayList<>();
    ZTagEntity zTagEntity = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent().getvStypeMap().get(channel);
    Map<String, Integer> cityInfoMap = MutableCaches.getInstance().CITIES.getCacheContent();

    Set<Integer> stype = new HashSet<>();
    Set<Integer> stypegroup = new HashSet<>();
    if(tuples.size() == 1){
      for(List<Word> list:tuples){
        if(list.size() == 1) {
          String name = list.get(0).getName();
          System.out.println("word name:"+name);
          /////国内城市为目的地，需要修改
          if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(name)){
            searchParameterOrigin.reconstructWithCity(name);
            //tuples = new HashSet<>();
            tuples.clear();
            if(cityInfoMap.containsKey(name)) {
              Segment segment = new Segment(name, "city", cityInfoMap.get(name));
              segmentation.add(segment);
            }
          }else if(MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().containsKey(name)){
            searchParameterOrigin.reconstructWithCountry(list.get(0).getName());
            //tuples = new HashSet<>();
            tuples.clear();
            Segment segment = new Segment(name, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().get(name).intValue());
            segmentation.add(segment);
          } else if(zTagEntity.getS_type_group_map().containsKey(name)){
            preSKUType1.add(zTagEntity.getS_type_group_map().get(name));
          }else if(zTagEntity.getS_type_map().containsKey(name)){
            preSKUType2.add(zTagEntity.getS_type_map().get(name));
            preSKUType1.addAll(
              zTagEntity.getNegativeMap().get(zTagEntity.getS_type_map().get(name)));
          }else if(Constants.CONTINENT_MAP.containsKey(name)){
            //System.out.println("set continent");
            searchParameterOrigin.setContinent(name);
            //System.out.println("after set continent:"+searchParameterOrigin.getContinent());
          }
        }else {
          for(Word word: list){
            String name = word.getName();
            //System.out.println("Word Name:" + name);
            if(zTagEntity.getS_type_map().containsKey(name)){
              //System.out.println("stype name:" + name);
              stype.add(zTagEntity.getS_type_map().get(name));
            }
            if(zTagEntity.getS_type_group_map().containsKey(name)){
              //System.out.println("sgtype name:" + name);
              stypegroup.add(zTagEntity.getS_type_group_map().get(name));
            }
            //确定目的地
            if(canDefinDest) {
              if ((word.getFirstImpression() == Impression.IMPRESSION_CONTINENT)||Constants.CONTINENT_MAP.containsKey(name)) {
                //System.out.println("大洲");
                if (++n_Continent > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCon = word;
                }
              }else if(word.getFirstImpression() == Impression.IMPRESSION_COUNTRY||MutableCaches.getInstance().OVERSEA_COUNTRIES.getCacheContent().containsKey(name)){
                //System.out.println("国家识别~");
                if (++n_Country > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCou = word;
                }
              }else if(word.getFirstImpression() == Impression.IMPRESSION_CITY){
                //System.out.println("城市识别~");
                if (++n_City > 1) {
                  canDefinDest = false;
                  break;
                } else {
                  wordCit = word;
                }
              }
            }
          }
          //判断是否确定意图，未来会有新的逻辑，比如优先级
          if((stype.size() <= 1)&&(stypegroup.size() <= 1)){
            if(stypegroup.size() == 1){
              for(int j:stypegroup) {
                System.out.println("j:"+j);
                if (stype.size() == 1) {
                  for (int jk : stype) {
                    if (zTagEntity.getNegativeMap().get(jk).contains(j)){
                      preSKUType1.add(j);
                      preSKUType2.add(jk);
                      System.out.println("jk:"+jk);
                    }
                  }
                }else {
                  preSKUType1.add(j);
                }
              }
            }else {
              for (int jk : stype) {
                preSKUType2.add(jk);
                System.out.println("jk:" + jk);
                List<Integer> stgList = zTagEntity.getNegativeMap().get(jk);
                if(CollectionUtils.isNotEmpty(stgList)){
                  preSKUType1.addAll(stgList);
                }
              }
            }
          }

          //是否一个地方
          if(canDefinDest){
            if((n_City + n_Country + n_Continent) > 1){
              if(wordCit == null){
                String _country = wordCou.getName();
                String _continent = wordCon.getName();
                //System.out.println("城市为空:" + "国家:"+_country + "：大洲:"+_continent);
                if(_continent.equals(MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country))){
                  if(searchParameterOrigin.isCountryAbsent()) {
                    if(MutableCaches.getInstance().OVERSEA_COUNTRIES
                      .getCacheContent().containsKey(_country)) {
                      Segment segment = new Segment(_country, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES
                        .getCacheContent().get(_country));
                      segmentation.add(segment);
                    }
                  }
                  searchParameterOrigin.setDestCountryIf(_country);
                  searchParameterOrigin.setContinent(_continent);
                  list.remove(wordCon);
                  list.remove(wordCou);
                  if(CollectionUtils.isEmpty(list)){
                    tuples.clear();
                  }
                }
              }else if(wordCou == null){
                String _city = wordCit.getName();
                String _continent = wordCon.getName();
                //System.out.println("国家为空:" + "国家:"+_city + "：大洲:"+_continent);
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(_city);
                if(CollectionUtils.isNotEmpty(_countryList)){
                  for(String _country : _countryList){
                    String continent1 = MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country);
                    if(_continent.equals(continent1)){
                      //小bug
                      if(searchParameterOrigin.isCityAbsent()){
                        if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                          if(cityInfoMap.containsKey(_city)) {
                            Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                            segmentation.add(segment);
                          }
                        }
                      }
                      searchParameterOrigin.setDestCountryIf(_country);
                      searchParameterOrigin.setDestIf(_city);
                      list.remove(wordCon);
                      list.remove(wordCit);
                      if(CollectionUtils.isEmpty(list)){
                        tuples.clear();
                      }
                    }
                  }
                }
              }else if(wordCon == null){
                //System.out.println("大洲为空");
                String _city = wordCit.getName();
                String _country = wordCou.getName();
                //System.out.println("大洲为空:" + "国家:"+_city + "：国家:"+_country);
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(
                  _city);
                if(CollectionUtils.isNotEmpty(_countryList)) {
                  for (String str : _countryList) {
                    if(_country.equals(str)){
                      if(searchParameterOrigin.isCityAbsent()){
                        if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                          if(cityInfoMap.containsKey(_city)) {
                            Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                            segmentation.add(segment);
                          }
                        }
                      }
                      searchParameterOrigin.setDestCountryIf(_country);
                      searchParameterOrigin.setDestIf(_city);
                      list.remove(wordCit);
                      list.remove(wordCou);
                      if(CollectionUtils.isEmpty(list)){
                        tuples.clear();
                      }
                    }
                  }
                }
              }else {
                String _city = wordCit.getName();
                String _country = wordCou.getName();
                String _continent = wordCon.getName();
                //List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().get(_city);
                List<String> _countryList = MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().get(_city);
                if(_continent.equals(MutableCaches.getInstance().COUNTRY_CONTINENT_MAP.getCacheContent().get(_country))) {
                  if (CollectionUtils.isNotEmpty(_countryList)) {
                    for (String str : _countryList) {
                      if (_country.equals(str)) {
                        if(searchParameterOrigin.isCityAbsent()){
                          if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                            if(cityInfoMap.containsKey(_city)) {
                              Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                              segmentation.add(segment);
                            }
                          }
                        }
                        searchParameterOrigin.setDestIf(_city);
                        searchParameterOrigin.setDestCountryIf(_country);
                        list.remove(wordCit);
                        list.remove(wordCou);
                        list.remove(wordCon);
                        if(CollectionUtils.isEmpty(list)){
                          tuples.clear();
                        }
                      }
                    }
                  }
                }
              }
            }else if(n_City == 1){
              String _city = wordCit.getName();
              if(MutableCaches.getInstance().CITY_COUNTRY_MAP_ALL.getCacheContent().containsKey(_city)){
                //if(MutableCaches.getInstance().CITY_COUNTRY_MAP_LIST.getCacheContent().containsKey(_city)){
                if(searchParameterOrigin.isCityAbsent()){
                  if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                    if(cityInfoMap.containsKey(_city)) {
                      Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                      segmentation.add(segment);
                    }
                  }
                }
                searchParameterOrigin.reconstructWithCity(_city);
                list.remove(wordCit);
              }else if(MutableCaches.getInstance().TAIWAN_MAP.getCacheContent().contains(_city)){
                if(searchParameterOrigin.isCityAbsent()){
                  if(MutableCaches.getInstance().OVERSEA_CITIES.getCacheContent().containsKey(_city)) {
                    if(cityInfoMap.containsKey(_city)) {
                      Segment segment = new Segment(_city, "city", cityInfoMap.get(_city));
                      segmentation.add(segment);
                    }
                  }
                }
                searchParameterOrigin.reconstructWithCity(_city);
                list.remove(wordCit);
              }
            }else if(n_Country == 1){
              String _country = wordCou.getName();
              if(searchParameterOrigin.isCountryAbsent()) {
                if(MutableCaches.getInstance().OVERSEA_COUNTRIES
                  .getCacheContent().containsKey(_country)) {
                  Segment segment = new Segment(_country, "country", MutableCaches.getInstance().OVERSEA_COUNTRIES
                    .getCacheContent().get(_country));
                  segmentation.add(segment);
                }
              }
              searchParameterOrigin.setDestCountryIf(_country);
              list.remove(wordCou);
            }else if(n_Continent == 1){
              searchParameterOrigin.setContinent(wordCon.getName());
            }
          }
        }
      }
    }else{
      /*for(List<Word> list: tuples){
        for(Word word: list){
          if(Constants.HOT_PS_1.containsKey(word.getName())){
            preSKUType1.add(Constants.HOT_PS_1.get(word.getName()));
          }else if(Constants.HOT_PS_2.containsKey(word.getName())){
            preSKUType2.add(Constants.HOT_PS_2.get(word.getName()));
          }
          //确定目的地
        }
      }*/
    }

    return segmentation;
  }


}

